#!/bin/python3
# encoding=utf-8
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import math
import binascii
import os
import tkinter as tk
from tkinter import filedialog
import ctypes

def chinese_code():
    plt.rcParams['font.sans-serif']=['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
def select_csv():
    path = filedialog.askopenfile()
    if path != None:
        return path.name
    return None

def _predict_str2hex(data):
    htitle=['VAL0','VAL1','VAL2','VAL3','VAL4','VAL5','VAL6','VAL7','VAL8','VAL9','VALA','VALB','VALC','VALD','VALE','VALF','VAL10','VAL11','VAL12','VAL13','VAL14','VAL15','VAL16','VAL17','VAL18','VAL19','VAL1A','VAL1B','VAL1C','VAL1D','VAL1E','VAL1F','VAL20','VAL21','VAL22','VAL23','VAL24','VAL25','VAL26','VAL27','VAL28','VAL29','VAL2A','VAL2B','VAL2C','VAL2D','VAL2E','VAL2F','VAL30','VAL31','VAL32','VAL33','VAL34','VAL35','VAL36','VAL37','VAL38','VAL39','VAL3A','VAL3B','VAL3C','VAL3D','VAL3E','VAL3F','VAL40','VAL41','VAL42','VAL43','VAL44','VAL45','VAL46','VAL47','VAL48','VAL49','VAL4A','VAL4B','VAL4C','VAL4D','VAL4E','VAL4F','VALB0','VALB1','VALB2','VALB3','VALB4','VALB5','VALB6','VALB7','VALB8','VALB9','VALBA','VALBB','VALBC','VALBD','VALBE','VALBF','VALD0','VALD1','VALD2','VALD3','VALD4','VALD5','VALD6','VALD7','VALD8','VALD9','VALDA','VALDB','VALDC','VALDD','VALDE','VALDF']
    iterH = iter(htitle)
    lista = list(data)   # 获取标题列表，
    lista = data.columns.values
    for iH in iterH:
        # 对于缺失项目添0
        if iH not in lista:
            data[iH] = 0
            continue


        tlist = []
        iterD = iter(data[iH])
        for iD in iterD:
            tlist.append(int(iD, 16))
        data[iH] = np.array(tlist)
    return data
def _predict_capacity_type(data):
    return data;

def _predict_percentage_type(data):
    # 百分比参数
    # 特殊：VAL46 VALFF未定义
    htitle = ['VAL5', 'VAL6', 'VAL7', 'VAL46', 'VALE', 'VALC', 'VALD', 'VALDE','VAL35', 'VAL10', 'VAL45', 'VAL4D', 'VAL1F', 'VALF', 'VAL4A', 'VALDC', 'VALDF']
    iterH = iter(htitle)
    for iH in iterH:
        data[iH] = data[iH] /256
    return data
def _predict_voltage_type(data):
    # 电压型参数
    htitle = ['VAL9', 'VAL19', 'VALD5', 'VALD6', 'VALD7', 'VALD8', 'VALD1', 'VALD2', 'VALD3', 'VALD4','VALD9']
    iterH = iter(htitle)
    for iH in iterH:
        data[iH] = data[iH]  * 0.078125
    return data;

def _predict_current_type(data):
    # 电流型参数
    htitle = ['VAL4', 'VALA', 'VALB']
    iterH = iter(htitle)
    for iH in iterH:
        tlist = []
        iterD = iter(data[iH])
        for iD in iterD:
            tlist.append(ctypes.c_int16(iD).value)
        data[iH] = np.array(tlist)
        data[iH] = data[iH] * 0.0015625/0.01
    return data
def _predict_tempture_type(data):
    # htitle = ['VAL8',]
    # iterH = iter(htitle)
    # for iH in iterH:
    #     data[iH] = data[iH]  /256
    # return data;
    htitle = ['VAL8']
    iterH = iter(htitle)
    for iH in iterH:
        tlist = []
        iterD = iter(data[iH])
        for iD in iterD:
            tlist.append(ctypes.c_int16(iD).value)
        data[iH] = np.array(tlist)
        data[iH] = data[iH] / 256
    return data
    
def _predict_resistance_type(data):

    return data
def _predict_time_type(data):
    htitle = ['VAL11', 'VAL20']
    # 转换时间部分非常卡

    # data[data['VAL11'] == 0xffff] = 0
    # data[data['VAL20'] == 0xffff] = 0
    
    # data['VAL20'] = data['VAL20'] * 5.625
    # data['VAL11'] = data['VAL11'] * 5.625
    # data[data[htitle] > 0xfff0] = 0
    # data[htitle] = data[htitle] * 5.625
    # iterH = iter(htitle)
    # for iH in iterH:
    #     data[iH] = data[iH]  * 5.625
        
    return data;
    return data
# def check_cum(data):
#     C = data["VAL6"] # 电容
#     V = data['VAL9'] # 电压
#     A = data['VALA'] # 电流
    
#     print(len(C))
#     index = np.where([
#         [C >= 65] and
#         [C <= 70]
#     ])[-1]
#     # print(len(index))
#     X1 = V[index]
#     X2 = A[index]
#     print(sum(X1*X2))

#     index = np.where([
#         [C >= 60] and
#         [C <= 65]
#     ])[-1]
#     X1 = V[index]
#     X2 = A[index]
#     print(sum(X1*X2))

def load_data(fname):
    fd = open(fname)
    data = pd.read_csv(fd)

    data = _predict_str2hex(data)


    data = _predict_capacity_type(data)
    data = _predict_percentage_type(data)
    data = _predict_voltage_type(data)
    data = _predict_current_type(data)
    data = _predict_tempture_type(data)
    data = _predict_resistance_type(data)
    data = _predict_time_type(data)


    # check_cum(data)
    return data
def func(p,x):
    k,b=p
    return k*x+b
def draw_line(data, title=""):
    Y1 = data["VAL6"] # 电容
    Y2 = data['VAL9'] # 电压
    Y3 = data['VALA'] # 电流
    the_range = list(range(0, len(Y1)))
    Xi=np.array(the_range)

    
    
    
    fig = plt.figure()
    axL  = fig.add_subplot(111)
    axR = axL.twinx()
    axR2 = axL.twinx()
    
    plt.title(title + "放电点参考")
    axL.set_xlabel("时间(s)")
    axL.set_ylabel("C(%)") # 容量
    axR.set_ylabel("V(mV)") # 电压
    axR2.set_ylabel("A(mA)") # 电流
    
    axL.plot(Xi, Y1, color='r')
    axR.plot(Xi, Y2, linewidth=3, color='b')
    axR2.plot(Xi, Y3, linewidth=3, color='g')
    axL.legend(labels=["C"], loc='upper left') # 容量
    axR.legend(labels=["V"], loc='upper right') # 电压
    axR2.legend(labels=["A"], loc='upper right') # 电流
    
    
    # 绘制若干切线
    # I = []
    # I.append(fun(Y2, 60, 10, 'r'))
    # I.append(fun(Y2, 40, 10, 'b'))
    # I.append(fun(Y2, 30, 10, 'g'))
    # I.append(fun(Y2, 20, 10, 'y'))
    plt.legend(labels=['60min', '40min', '30min', '20min', '11'], loc='lower left')
    # return I
def figure_discharge(data):
    # draw(data, title="title")
    draw_line(data, title="")
    plt.show()


def draw_3t1curve(data, title=""):
    title = os.path.basename(title)
    # Y1 = data["Capacity"]
    # Y2 = data['Current']
    # Y3 = data['Volt']

    Y1 = data["VAL6"] # 电容
    Y2 = data['VAL9'] # 电压
    Y3 = data['VALA'] # 电流
    the_range = list(range(0, len(Y2)))
    Xi=np.array(the_range)

    
    
    
    fig = plt.figure()
    fig.set_size_inches(9.4,9.3)
    # fig.set_size_inches(10.0,10.0)
    axL = fig.add_subplot(211)
    axR = axL.twinx()
    axR2 = axL.twinx()
    
    
    plt.title(title)
    axL.set_xlabel("sec)")
    axL.set_ylabel("%")
    axR.set_ylabel("mV")
    # axR.set_xlabel("时间(4s)")
    axR2.set_ylabel("mA", labelpad=-4)
    axR2.spines['right'].set_position(('axes', 1.15))
    # print(axR2.spines)
    # axR2.set_frame_on(True)
    # axR2.patch.set_visible(False)
    
    
    lns1 = axL.plot(Xi, Y1, linewidth=3, linestyle="-",  color='r', alpha=0.8)
    lns2 = axR.plot(Xi, Y2, linewidth=1, linestyle="--",  color='b', alpha=0.8)
    lns3 = axR2.plot(Xi, Y3, linewidth=1, linestyle="-", color='g', alpha=0.8)
    lns = lns1+lns2+lns3
    labs = [l.get_label() for l in lns]
    labs = ["C", "V", "A"]
    axL.legend(lns, labs,loc="center left")

    fig.subplots_adjust(right=0.75, hspace=0.5)
    if 0:
        axL = fig.add_subplot(212)
        axR = axL.twinx()
        axR2 = axL.twinx()

        Y1 = data['VAL8']  # 温度
        Y2 = data['VAL11']  # 充满
        Y3 = data['VAL20']  # 放完
        
        lns_1 = axL.plot(Xi, Y1, linewidth=3, linestyle="-",  color='r', alpha=0.8)
        lns_2 = axR.plot(Xi, Y2, linewidth=1, linestyle="--",  color='b', alpha=0.8)
        lns_3 = axR2.plot(Xi, Y3, linewidth=1, linestyle="-", color='g', alpha=0.8)
        lns_ = lns_1+lns_2+lns_3
        labs = [l.get_label() for l in lns_]
        labs = ["Tempture", "TTE", "TTF"]
        axL.legend(lns_, labs,loc="center left")
    else:
        axL = fig.add_subplot(212)
        axR = axL.twinx()
        axL.set_ylabel("℃")

        Y1 = data['VAL8']  # 温度
        lns_1 = axL.plot(Xi, Y1, linewidth=3, linestyle="-",  color='r', alpha=0.8)
        lns_ = lns_1
        labs = [l.get_label() for l in lns_]
        axL.legend(lns_, labs,loc="center left")
        # plt.ylabel("℃")
        # plt.legend("Tempture")

# 比较从i2c直接获取数据和内核驱动为了优化算法舍弃部分精度
def draw_diff_raw_mod(data):
    pass
def figure_3t1curve(data, fname="", index=[0,0]):
    draw_3t1curve(data, title=fname)
    plt.show()    
def draw_mutil(data, cols, title="un title", index=[]):
    plt.figure(title)
    # plt.subplots_adjust(left=0.1, bottom=0.1, right=0.9, top=0.9, hspace=0.2, wspace=0.2)

    for i in range(len(cols)):
        # print(cols[i]['name'])
        if cols[i]['name'] == '':
            continue
        plt.subplot(4,4,i+1)
        plt.ylabel(cols[i]['name'])
        plt.plot(data[cols[i]['col']])

    plt.legend()

    pass

def figure_3curve(data, index=[0,0], fname=""):
    
    fname = os.path.basename(fname)
    if len(index) > 2:
        title = fname + " Volt>3780 ID:" + str(index[0]) + "~" + str(index[-1])
    else:
        title = fname

    cols = [{'col':'VAL0', 'name':'Status'},{'col':'VAL1', 'name':'VAlrtTh'},{'col':'VAL2', 'name':'TAlrtTh'},{'col':'VAL3', 'name':'SAlrtTh'},{'col':'VAL4', 'name':'AtRate'},{'col':'VAL5', 'name':'RepCap'},{'col':'VAL6', 'name':'RepSOC'},{'col':'VAL7', 'name':'Age '},{'col':'VAL8', 'name':'Temp'},{'col':'VAL9', 'name':'VCell'},{'col':'VALA', 'name':'Current'},{'col':'VALB', 'name':'AvgCurrent'},{'col':'VALC', 'name':'QResidual'},{'col':'VALD', 'name':'MixSOC'},{'col':'VALE', 'name':'AvSOC'},{'col':'VALF', 'name':'MixCap'}]
    draw_mutil(data, cols, title='0x00-0x0f')
    # cols = [{'col':'VAL10', 'name':'FullCap'},{'col':'VAL11', 'name':'TTE'},{'col':'VAL12', 'name':'QRTable00'},{'col':'VAL13', 'name':'FullSocThr'},{'col':'VAL14', 'name':'RCellRCell'},{'col':'VAL15', 'name':'RFast'},{'col':'VAL16', 'name':'AvgTA'},{'col':'VAL17', 'name':'Cycles'},{'col':'VAL18', 'name':'DesignCap'},{'col':'VAL19', 'name':'AvgVCell'},{'col':'VAL1A', 'name':'MaxMinTemp'},{'col':'VAL1B', 'name':'MaxMinVolt'},{'col':'VAL1C', 'name':'MaxMinCurr'},{'col':'VAL1D', 'name':'Confg'},{'col':'VAL1E', 'name':'IChgTerm'},{'col':'VAL1F', 'name':'AvCap'}]
    # draw_mutil(data, cols, title='0x10-0x1f')
    # cols=[{'col':'VAL20', 'name':'TTF'},{'col':'VAL21', 'name':'DevName'},{'col':'VAL22', 'name':'QRTable10'},{'col':'VAL23', 'name':'FullCapNom'},{'col':'VAL24', 'name':''},{'col':'VAL25', 'name':''},{'col':'VAL26', 'name':''},{'col':'VAL27', 'name':'AIN0'},{'col':'VAL28', 'name':'LearnCfg'},{'col':'VAL29', 'name':'FilterCfg'},{'col':'VAL2A', 'name':'RelaxCfg'},{'col':'VAL2B', 'name':'MiscCfg'},{'col':'VAL2C', 'name':'TGain'},{'col':'VAL2D', 'name':'TOff'},{'col':'VAL2E', 'name':'CGain'},{'col':'VAL2F', 'name':'COff'},]
    # draw_mutil(data, cols, title='0x20-0x2f')
    # cols=[{'col':'VAL30', 'name':''},{'col':'VAL31', 'name':''},{'col':'VAL32', 'name':'QRTable20'},{'col':'VAL33', 'name':''},{'col':'VAL34', 'name':''},{'col':'VAL35', 'name':'FullCapRep'},{'col':'VAL36', 'name':'IAvgEmpty'},{'col':'VAL37', 'name':''},{'col':'VAL38', 'name':'RComp0'},{'col':'VAL39', 'name':'TempCo'},{'col':'VAL3A', 'name':'VEmpty'},{'col':'VAL3B', 'name':''},{'col':'VAL3C', 'name':''},{'col':'VAL3D', 'name':'FStat'},{'col':'VAL3E', 'name':'Timer'},{'col':'VAL3F', 'name':'ShdnTimer'},]
    # draw_mutil(data, cols, title='0x30-0x3f')
    # cols=[{'col':'VAL40', 'name':''},{'col':'VAL41', 'name':''},{'col':'VAL42', 'name':'QRTable30'},{'col':'VAL43', 'name':''},{'col':'VAL44', 'name':''},{'col':'VAL45', 'name':'dQAcc'},{'col':'VAL46', 'name':'dPAcc'},{'col':'VAL47', 'name':''},{'col':'VAL48', 'name':''},{'col':'VAL49', 'name':''},{'col':'VAL4A', 'name':'VFRemCap'},{'col':'VAL4B', 'name':''},{'col':'VAL4C', 'name':''},{'col':'VAL4D', 'name':'QH'},{'col':'VAL4E', 'name':''},{'col':'VAL4F', 'name':''},]
    # draw_mutil(data, cols, title='0x40-0x4f')
    # cols=[{'col':'VALB0', 'name':'Status2'},{'col':'VALB1', 'name':''},{'col':'VALB2', 'name':''},{'col':'VALB3', 'name':''},{'col':'VALB4', 'name':'IAlrtTh'},{'col':'VALB5', 'name':''},{'col':'VALB6', 'name':''},{'col':'VALB7', 'name':''},{'col':'VALB8', 'name':'VShdnCfg'},{'col':'VALB9', 'name':'AgeForecast'},{'col':'VALBA', 'name':'HibCfg'},{'col':'VALBB', 'name':'Confg2'},{'col':'VALBC', 'name':'VRipple'},{'col':'VALBD', 'name':'PackCfg'},{'col':'VALBE', 'name':'TimerH'},{'col':'VALBF', 'name':''},]
    # draw_mutil(data, cols, title='0xb0-0xbf')
    # cols=[{'col':'VALD0', 'name':''},{'col':'VALD1', 'name':'AvgCell4'},{'col':'VALD2', 'name':'AvgCell3'},{'col':'VALD3', 'name':'AvgCell2'},{'col':'VALD4', 'name':'AvgCell1'},{'col':'VALD5', 'name':'Cell4'},{'col':'VALD6', 'name':'Cell3'},{'col':'VALD7', 'name':'Cell2'},{'col':'VALD8', 'name':'Cell1'},{'col':'VALD9', 'name':'CellX'},{'col':'VALDA', 'name':'Batt'},{'col':'VALDB', 'name':''},{'col':'VALDC', 'name':'AtQResidual'},{'col':'VALDD', 'name':'AtTTE'},{'col':'VALDE', 'name':'AtAvSOC'},{'col':'VALDF', 'name':'AtAvCap'},]
    # draw_mutil(data, cols, title='0xd0-0xdf')
    plt.show()

class dlg_battery:
    def __init__(self, master):
        self.root   = master
        self.frm_left   = tk.Frame(master = self.root)
        self.frm_left.grid(row=1, column=4)
        self._init_param_()
        self._init_left(self.frm_left)
    def _init_param_(self):
        self.data = None
        self.fname = None
    def _init_left(self, master):
        btn1 = tk.Button(master=master, text=u"打开文件" ,  width=10, height=3, bg="PaleGreen")
        btn2 = tk.Button(master=master, text=u"多曲线" ,  width=10, height=3, bg="PaleGreen")
        btn3 = tk.Button(master=master, text=u"放电特性" ,  width=10, height=3, bg="PaleGreen")
        btn4 = tk.Button(master=master, text=u"放电积分" ,  width=10, height=3, bg="PaleGreen")
        btn5 = tk.Button(master=master, text=u"TODO" ,  width=10, height=3, bg="PaleGreen")
        
        btn1.grid(row=0,column=0, padx=10)
        btn2.grid(row=0,column=1, padx=10)
        btn3.grid(row=0,column=2, padx=10)
        btn4.grid(row=0,column=3, padx=10)
        btn5.grid(row=0,column=4, padx=10)
        
        btn1.bind("<ButtonRelease-1>", self.on_btn1_click)
        btn2.bind("<ButtonRelease-1>", self.on_btn2_click)
        btn3.bind("<ButtonRelease-1>", self.on_btn3_click)
        btn4.bind("<ButtonRelease-1>", self.on_btn4_click)
        btn5.bind("<ButtonRelease-1>", self.on_btn5_click)
    def on_btn1_click(self, event):
        self.fname = select_csv()
        if self.fname == None:
            return None
    
        self.data = load_data(self.fname);
        pass
    def on_btn2_click(self, event):
        print(self.data)
        if self.data is None:
            self.on_btn1_click(None);
        figure_3curve(self.data, []);
        pass
    def on_btn3_click(self, event):
        if self.data is None:
            self.on_btn1_click(None);
        figure_3t1curve(self.data, fname=self.fname)
        pass
    def on_btn4_click(self, event):
        if self.data is None:
            self.on_btn1_click(None);
        # draw_power(self.data)
        draw_sum_power(self.data, title="")

        
        plt.show();
        pass
    def on_btn5_click(self, event):
        if self.data is None:
            self.on_btn1_click(None);
        # draw_3t1curve(self.data, title="")
        index = np.where([
            [self.data['Capacity'] <= 74],
            [self.data['Capacity'] >= 68],
        ])[-1]
        # figure_3t1curve(self.data, fname=self.fname, index=[index[0], index[-1]])
        figure_3t1curve(self.data, fname=self.fname, index=[0, 0])
        
        pass
    pass

if __name__ == '__main__':

    master = tk.Tk()
    chinese_code()
    dlg = dlg_battery(master)
    master.mainloop();
    exit(0)